package com.ruoyi.accountant.service.impl;

import com.ruoyi.system.domain.TBalance;
import com.ruoyi.system.service.ITBalanceService;
import com.ruoyi.system.service.ITCurrencyService;
import com.ruoyi.web.core.config.AppConf;
import com.ruoyi.accountant.domain.*;
import com.ruoyi.accountant.domain.other.CallResult;
import com.ruoyi.accountant.mapper.AccountMapper;
import com.ruoyi.accountant.mapper.BalanceMapper;
import com.ruoyi.accountant.mapper.TransactionDetailMapper;
import com.ruoyi.accountant.service.*;
import com.ruoyi.accountant.utils.ExchangeRateUtils;
import com.ruoyi.web.web.form.IncomeForm;
import com.ruoyi.web.web.form.PayForm;
import com.ruoyi.web.web.form.TransferForm;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Service
@Transactional
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountMapper accountDao;

    @Resource
    private AccountMapper accountMapper;
    @Autowired
    private BalanceMapper balanceDao;

    @Autowired
    private BalanceMapper balanceMapper;

    @Resource
    private ITBalanceService itBalanceService;

    @Autowired
    private TransactionDetailMapper transactionDetailDao;


    @Autowired
    private TransactionDetailMapper transactionDetailMapper;

    @Autowired
    private AccountDetailService accountDetailService;

    @Autowired
    private ReasonDetailService reasonDetailService;

    @Autowired
    private InaccountService inaccountService;

    @Autowired
    private CurrencyService currencyService;

    @Resource
    private ITCurrencyService itCurrencyService;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private SettingService settingService;

    @Autowired
    private ReasonService reasonService;

    @Override
    public void save(Account account) {
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        account.setCreatetime(timestamp);
        account.setDeleted(AppConf.OFF);
        account.setRecentlyTime(timestamp);
        account.setStop(AppConf.OFF);


        accountMapper.insert(account);
    }

    @Override
    public List<Account> findAll() {
        return accountMapper.findAllByDeleted(AppConf.OFF);
    }

    @Override
    public Account findById(long l) {
        return accountMapper.selectByPrimaryKey(l);
    }

    @Override
    public int update(Account byId) {
       return accountMapper.updateByPrimaryKeySelective(byId);
    }

    @Override
    public int deleteById(Long aid) {
        List<Device> deviceList = deviceService.findUnfinishedByOfAccount(aid);
        if(deviceList.size() == 0) {
            Account byId = findById(aid);
            byId.setDeleted(AppConf.ON);
          return  update(byId);
        }

        return 0;
    }

    /***
     * 构建同日收入和非同日收入
     */
    private TransactionDetail buildIncome(IncomeForm accountForm) {
        // 查询系统设置
        Setting setting = settingService.findById(AppConf.APP_SETTING_ID);
        Integer mainCurrency = setting.getMainCurrency(); // 系统默认币种类型

        // 如果录入的币种类型不等于系统的主用币种，查询汇率和主币种对应的金额
        Double mainCurrencyMoney = accountForm.getMoney();
        if(accountForm.getCurrency() != mainCurrency) {
            mainCurrencyMoney = ExchangeRateUtils.exchange(accountForm.getCurrencyName(), itCurrencyService.selectTCurrencyByCid(Long.valueOf(String.valueOf(mainCurrency))).getEnName(), accountForm.getMoney());
        }

        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        Account account = findById(accountForm.getAccount());

        BigDecimal balance = new BigDecimal(accountForm.getMoney() - accountForm.getServiceCharge());
        BigDecimal tax;
        if(accountForm.getTaxRateType().equals("应税")) {
            tax = new BigDecimal(balance.doubleValue() - (balance.doubleValue() / (1 + accountForm.getTaxRate() / 100D)));
        } else {
            tax = new BigDecimal(0);
        }

        // 增加余额
        Balance b = balanceMapper.findAllByOfAccountAndOfCurrency(account.getAid(), accountForm.getCurrency());
        if(b == null) { // 余额不存在
            b = new Balance();
            b.setOfCurrency(accountForm.getCurrency());
            b.setOfAccount(account.getAid());
            b.setBalance(balance);
            b.setCreatetime(timestamp);
            int i=balanceMapper.insert(b);
        }else{
            Balance b1 = new Balance();
            b1.setBid(b.getBid());
            b1.setOfCurrency(b.getOfCurrency());
            b1.setOfAccount(b.getOfAccount());
            b1.setBalance(b.getBalance().add(balance));
            b1.setCreatetime(timestamp);
            int i=balanceMapper.updateByPrimaryKey(b1);
        }


        //交易记录明细
        TransactionDetail detail = new TransactionDetail();
        detail.setDtype("收入");
        if(!accountForm.getTransactionType().equals("应收款")) {
            detail.setTransactionDate(accountForm.getIncomeDate());
        }

        detail.setProofDate(accountForm.getProofDate());
        detail.setOfReason(accountForm.getReasonId());
        detail.setMoney(balance);
        detail.setOfAccount(account.getAid());
        detail.setObject(accountForm.getObject());
        detail.setComment(accountForm.getComment());
        detail.setTag(accountForm.getTag());
        detail.setTax(tax);
        detail.setOfCompany(accountForm.getOfCompany());
        detail.setInvoice(accountForm.getInvoice());
        detail.setAttachment(accountForm.getAttachment());
        detail.setDeleted(AppConf.OFF);
        detail.setOfDevice(null);
        detail.setInAccount(null);
        detail.setCreatetime(timestamp);
        detail.setMainCurrencyMoney(new BigDecimal(mainCurrencyMoney));
        detail.setTaxRate(accountForm.getTaxRate());
        detail.setWithDeposit(AppConf.OFF);

        // 资金账户明细
        AccountDetail accountDetail = new AccountDetail();
        accountDetail.setDtype("收入");
        accountDetail.setOutmoney(new BigDecimal(0));
        accountDetail.setInmoney(balance);
        accountDetail.setBalance(b.getBalance());
        accountDetail.setComment(accountForm.getComment());
        accountDetail.setOfReason(accountForm.getReasonId());
        accountDetail.setProofDate(accountForm.getProofDate());
        accountDetail.setObject(accountForm.getObject());
        accountDetail.setTag(accountForm.getTag());
        accountDetail.setAttachment(accountForm.getAttachment());
        accountDetail.setOfAccount(account.getAid());
        accountDetail.setDeleted(AppConf.OFF);
        accountDetail.setOfDevice(null);
        accountDetail.setCreatetime(timestamp);
        accountDetail.setTransactionDate(new Date());
        accountDetail.setOfCompany(accountForm.getOfCompany());
        detail.setOfCurrency(accountForm.getCurrency());


        // 会计项目明细
        ReasonDetail reasonDetail = new ReasonDetail();
        reasonDetail.setDtype("收入");
        reasonDetail.setTransactionDate(timestamp);
        reasonDetail.setComment(accountForm.getComment());
        reasonDetail.setDebtorMoney(new BigDecimal(0));
        reasonDetail.setCreditorMoney(new BigDecimal(0));
        reasonDetail.setObject(accountForm.getObject());
        reasonDetail.setTag(accountForm.getTag());
        reasonDetail.setTax(tax);
        reasonDetail.setInvoice(accountForm.getInvoice());
        reasonDetail.setAttachment(accountForm.getAttachment());
        reasonDetail.setOfReason(accountForm.getReasonId());
        reasonDetail.setDeleted(AppConf.OFF);
        reasonDetail.setOfDevice(null);
        reasonDetail.setCreatetime(timestamp);
        reasonDetail.setOfCompany(accountForm.getOfCompany());

        reasonDetailService.save(reasonDetail);

        accountDetailService.save(accountDetail);

        detail.setReasonDetailId(reasonDetail.getRid());
        detail.setAccountDetailId(accountDetail.getAid());

        transactionDetailMapper.insert(detail);

        return detail;
    }

    /***
     * 构建应收款
     */
    private void buildUnpay(IncomeForm accountForm, Long depositId) {
        // 查询系统设置
        Setting setting = settingService.findById(AppConf.APP_SETTING_ID);
        Integer mainCurrency = setting.getMainCurrency(); // 系统默认币种类型

        // 如果录入的币种类型不等于系统的主用币种，查询汇率和主币种对应的金额
        Double mainCurrencyMoney = accountForm.getMoney();
        if(accountForm.getCurrency() != mainCurrency) {
            mainCurrencyMoney = ExchangeRateUtils.exchange(accountForm.getCurrencyName(), currencyService.findById(mainCurrency).getEnName(), accountForm.getMoney());
        }

        Timestamp timestamp = new Timestamp(System.currentTimeMillis());

        Account account = findById(accountForm.getAccount());

        BigDecimal balance = new BigDecimal(accountForm.getMoney() - accountForm.getServiceCharge());
        BigDecimal tax;
        if(accountForm.getTaxRateType().equals("应税")) {
            tax = new BigDecimal(balance.doubleValue() - (balance.doubleValue() / (1 + accountForm.getTaxRate() / 100D)));
        } else {
            tax = new BigDecimal(0);
        }

        TransactionDetail detail = new TransactionDetail();
        detail.setDtype("应收款");
        detail.setTransactionDate(accountForm.getIncomeDate());
        detail.setProofDate(accountForm.getProofDate());
        detail.setOfReason(accountForm.getReasonId());
        detail.setMoney(balance);
        detail.setOfAccount(account.getAid());
        detail.setObject(accountForm.getObject());
        detail.setComment(accountForm.getComment());
        detail.setTag(accountForm.getTag());
        detail.setTax(tax);
        detail.setInvoice(accountForm.getInvoice());
        detail.setAttachment(StringUtils.isEmpty(accountForm.getAttachment()) ? null : accountForm.getAttachment());
        detail.setDeleted(AppConf.OFF);
        detail.setOfDevice(null);
        detail.setInAccount(null);
        detail.setCreatetime(timestamp);
        detail.setMainCurrencyMoney(new BigDecimal(mainCurrencyMoney));
        detail.setTaxRate(accountForm.getTaxRate());
        detail.setOfCurrency(accountForm.getCurrency());
        detail.setOfCompany(accountForm.getOfCompany());
        detail.setServiceCharge(accountForm.getServiceCharge());
        detail.setTaxRateType(accountForm.getTaxRateType());

        if(depositId != null) {
            detail.setDepositId(depositId);
            detail.setWithDeposit(AppConf.ON);
        } else {
            detail.setWithDeposit(AppConf.OFF);
        }

        transactionDetailMapper.insert(detail);
    }

    @Override
    public int income(IncomeForm accountForm) {
        if(!accountForm.getTransactionType().equals("应收款")) { // 同日收入/同日支出
            //如果选择销货收入，新增订金选项，出现售价栏位以售价减去订金金额后 建立一笔相对应的应收款和同日收入。即产生两笔交易。
            if(accountForm.getTransactionType().equals("同日收入") && accountForm.getDeposit() != null && accountForm.getDeposit() > 0) { // 有订金建立同日收入和应收款
                double unpay = accountForm.getMoney() - accountForm.getDeposit(); // 未收款额度

                // 构建同日收入并且标注订金;
                IncomeForm paidIncome = new IncomeForm();
                BeanUtils.copyProperties(accountForm, paidIncome);
                paidIncome.setMoney(accountForm.getDeposit());
                TransactionDetail paidDetail = buildIncome(paidIncome);

                // 构建应收款
                IncomeForm unpayIncome = new IncomeForm();
                BeanUtils.copyProperties(accountForm, unpayIncome);
                unpayIncome.setMoney(unpay);
                buildUnpay(unpayIncome, paidDetail.getTid());
            } else {
                buildIncome(accountForm);

            }
        } else {
          buildUnpay(accountForm, null);

        }
        return 1;
    }

    @Override
    public CallResult pay(PayForm accountForm) {
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());

        Account account = findById(accountForm.getAccount());

        Setting byId = settingService.findById(AppConf.APP_SETTING_ID);
        Integer mainCurrency = byId.getMainCurrency();

        // 如果录入的币种类型不等于系统的主用币种，查询汇率和主币种对应的金额
        Double mainCurrencyMoney = accountForm.getMoney();

        if(accountForm.getCurrency() != mainCurrency) {
            mainCurrencyMoney = ExchangeRateUtils.exchange(accountForm.getCurrencyName(), currencyService.findById(mainCurrency).getEnName(), accountForm.getMoney());
        }

        BigDecimal balance = new BigDecimal(accountForm.getMoney() - accountForm.getServiceCharge());
        BigDecimal tax;
        if(accountForm.getTaxRateType().equals("应税")) {
            tax = new BigDecimal(balance.doubleValue() - (balance.doubleValue() / (1 + accountForm.getTaxRate() / 100D)));
        } else {
            tax = new BigDecimal(0);
        }

        if(!accountForm.getTransactionType().equals("应付款")) {
            // 支出余额
            Balance b = balanceMapper.findAllByOfAccountAndOfCurrency(account.getAid(), accountForm.getCurrency());
            if(b == null || b.getBalance().compareTo(balance) == -1) { // 余额不存在
                return CallResult.error("余额不足");
            } else {
                b.subtract(balance);
                balanceMapper.updateByPrimaryKeySelective(b);
            }

            //交易记录明细
            TransactionDetail detail = new TransactionDetail();
            detail.setDtype("支出");
            detail.setTransactionDate(accountForm.getPayDate());
            detail.setProofDate(accountForm.getProofDate());
            detail.setOfReason(accountForm.getReasonId());
            detail.setMoney(balance);
            detail.setOfAccount(account.getAid());
            detail.setObject(accountForm.getObject());
            detail.setComment(accountForm.getComment());
            detail.setTag(accountForm.getTag());
            detail.setTax(tax);
            detail.setAttachment(accountForm.getAttachment());
            detail.setDeleted(AppConf.OFF);
            detail.setOfDevice(null);
            detail.setInAccount(null);
            detail.setCreatetime(timestamp);
            detail.setOfCurrency(accountForm.getCurrency());
            detail.setMainCurrencyMoney(new BigDecimal(mainCurrencyMoney));
            detail.setTaxRate(accountForm.getTaxRate());
            detail.setOfCompany(accountForm.getOfCompany());


            // 资金账户明细
            AccountDetail accountDetail = new AccountDetail();
            accountDetail.setDtype("支出");
            accountDetail.setOutmoney(new BigDecimal(0));
            accountDetail.setInmoney(new BigDecimal(0)) ;
            accountDetail.setOutmoney(balance);
            accountDetail.setOfCompany(accountForm.getOfCompany());
            accountDetail.setBalance(b.getBalance());
            accountDetail.setComment(accountForm.getComment());
            accountDetail.setOfReason(accountForm.getReasonId());
            accountDetail.setProofDate(accountForm.getProofDate());
            accountDetail.setObject(accountForm.getObject());
            accountDetail.setTag(accountForm.getTag());
            accountDetail.setAttachment(accountForm.getAttachment());
            accountDetail.setOfAccount(account.getAid());
            accountDetail.setDeleted(AppConf.OFF);
            accountDetail.setOfDevice(null);
            accountDetail.setTransactionDate(new Date());
            accountDetail.setCreatetime(timestamp);

            // 会计项目明细
            ReasonDetail reasonDetail = new ReasonDetail();
            reasonDetail.setDtype("支出");
            reasonDetail.setTransactionDate(timestamp);
            reasonDetail.setComment(accountForm.getComment());
            reasonDetail.setDebtorMoney(new BigDecimal(0));
            reasonDetail.setCreditorMoney(new BigDecimal(0));
            reasonDetail.setObject(accountForm.getObject());
            reasonDetail.setTag(accountForm.getTag());
            reasonDetail.setTax(tax);
            reasonDetail.setAttachment(accountForm.getAttachment());
            reasonDetail.setOfReason(accountForm.getReasonId());
            reasonDetail.setDeleted(AppConf.OFF);
            reasonDetail.setOfDevice(null);
            reasonDetail.setCreatetime(timestamp);
            reasonDetail.setOfCompany(accountForm.getOfCompany());

            // 设备
            Reason reason = reasonService.findById(accountForm.getReasonId());
            if(reason.getRname().equals("机械设备") || reason.getRname().equals("办公设备")) {
                Device device = new Device();
                device.setDname(accountForm.getDeviceName());
                device.setDcode(accountForm.getDeviceCode());
                device.setMoney(new BigDecimal(accountForm.getMoney()));
                device.setCanUse(accountForm.getMonth());
                device.setStartdate(accountForm.getStartDate());
                device.setDcount(accountForm.getDeviceCount());
                device.setCreatetime(timestamp);
                device.setFinished(AppConf.OFF);
                device.setDeprecatedMonth(0);
                device.setOfAccount(accountForm.getAccount());
                device.setOfCurrency(accountForm.getCurrency());
                device.setOfCompany(accountForm.getOfCompany());
                detail.setFinished(AppConf.OFF);
                detail.setOfAccount(accountForm.getAccount());
                detail.setOfCurrency(accountForm.getCurrency());

                deviceService.save(device);
                System.out.println(device.getDid());
                detail.setOfDevice(device.getDid());
            }

            reasonDetailService.save(reasonDetail);
            accountDetailService.save(accountDetail);
            detail.setReasonDetailId(reasonDetail.getRid());
            detail.setAccountDetailId(accountDetail.getAid());

            transactionDetailMapper.insert(detail);
        } else {
            // 不增加余额，但生成未完成交易

            TransactionDetail detail = new TransactionDetail();
            detail.setDtype("应付款");
            detail.setTransactionDate(accountForm.getPayDate());
            detail.setProofDate(accountForm.getProofDate());
            detail.setOfReason(accountForm.getReasonId());
            detail.setMoney(balance);
            detail.setOfAccount(account.getAid());
            detail.setObject(accountForm.getObject());
            detail.setComment(accountForm.getComment());
            detail.setTag(accountForm.getTag());
            detail.setTax(tax);
            detail.setAttachment(accountForm.getAttachment());
            detail.setDeleted(AppConf.OFF);
            detail.setOfDevice(null);
            detail.setInAccount(null);
            detail.setCreatetime(timestamp);
            detail.setMainCurrencyMoney(new BigDecimal(mainCurrencyMoney));
            detail.setTaxRate(accountForm.getTaxRate());
            detail.setOfCurrency(accountForm.getCurrency());
            detail.setOfCompany(accountForm.getOfCompany());


            detail.setServiceCharge(accountForm.getServiceCharge());
            detail.setTaxRateType(accountForm.getTaxRateType());

            transactionDetailMapper.insert(detail);
        }
        return CallResult.ok();
    }

    @Override
    public void transfer(TransferForm form) {
        // 扣除转出账户余额
        // 生成transactionDetail 和 AccountDetail和 Inaccount
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        Balance outbalance = balanceMapper.findAllByOfAccountAndOfCurrency(form.getOutaccount(), form.getOutcurrency());
        Balance outbalance1 = balanceMapper.findAllByOfAccountAndOfCurrency(form.getInaccount(), form.getIncurrency());

        // 减去转移的金额和服务费
        outbalance.subtract(new BigDecimal(form.getTransferMoney() + ""));
        outbalance.subtract(new BigDecimal(form.getOutaccountServiceCharge()));
        BigDecimal exchange = new BigDecimal(0); // 交换金额

        if (form.getIncurrency().equals(form.getOutcurrency())) { // 如果币种类型一致
            // 减去账户金额
            exchange = new BigDecimal(form.getTransferMoney() - form.getInaccountServiceCharge());
            TBalance tBalance=new TBalance();
            tBalance.setBid(outbalance.getBid());
            tBalance.setBalance(outbalance.getBalance());
            itBalanceService.updateTBalance(tBalance);
        } else { // 查询汇率
            exchange = new BigDecimal(
                    ExchangeRateUtils.exchange(
                            form.getOutcurrencyName(), form.getIncurrencyName(), form.getTransferMoney()));
            if(outbalance1==null){
                TBalance tBalance=new TBalance();
                tBalance.setOfAccount(form.getInaccount());
                tBalance.setOfCurrency(Long.valueOf(String.valueOf(form.getIncurrency())));
                tBalance.setBalance(exchange);
                Date date = new Date();//获取当前的日期
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
                String str = df.format(date);//获取String类型的时间
                tBalance.setCreatetime(str);
                itBalanceService.insertTBalance(tBalance);
            }else {
                TBalance tBalance=new TBalance();
                tBalance.setBid(outbalance1.getBid());
                tBalance.setBalance(outbalance1.getBalance().add(exchange));
                itBalanceService.updateTBalance(tBalance);
            }

        }



        //交易记录明细
        Date endtime = new Date(form.getTransferDate().getTime() + new Date(form.getDays()).getTime());

        // 生成Inaccount
        Inaccount inaccount = new Inaccount();

        inaccount.setOutaccount(form.getOutaccount());
        inaccount.setInaccount(form.getInaccount());
        inaccount.setEndtime(endtime);
        inaccount.setFinished(AppConf.OFF);
        inaccount.setOutaccountCurrency(form.getOutcurrency());
        inaccount.setInaccountCurrency(form.getIncurrency());
        inaccount.setOutaccountMoney(new BigDecimal(form.getTransferMoney())); // 直接使用转换收的
        inaccount.setInaccountMoney(exchange);

        inaccount.setServiceCharge(form.getOutaccountServiceCharge());
        inaccount.setInaccountServiceCharge(form.getInaccountServiceCharge());

        inaccount.setCreatetime(timestamp);


        TransactionDetail detail = new TransactionDetail();
        detail.setDtype("转移");
        detail.setTransactionDate(form.getTransferDate());
        detail.setProofDate(endtime);
        detail.setMoney(new BigDecimal(form.getTransferMoney()));
        detail.setOfAccount(form.getOutaccount());
        detail.setInAccount(form.getInaccount());
        detail.setDeleted(AppConf.OFF);
        detail.setCreatetime(timestamp);
        detail.setOfCurrency(form.getOutcurrency());
        detail.setOfCompany(form.getOfCompany());
        detail.setInCurrency(form.getIncurrency());
        detail.setServiceCharge(form.getOutaccountServiceCharge());
        detail.setInServiceCharge(form.getInaccountServiceCharge());
        detail.setFinished(AppConf.OFF);
        if(form.getOutcurrency() == form.getIncurrency()) {
            detail.setMainCurrencyMoney(detail.getMoney());
        } else {
            detail.setMainCurrencyMoney(new BigDecimal(ExchangeRateUtils.exchange(form.getOutcurrencyName(), form.getIncurrencyName(), form.getTransferMoney())));
        }

        // 资金账户明细
        AccountDetail accountDetail = new AccountDetail();
        accountDetail.setDtype("转移");
        accountDetail.setOutmoney(new BigDecimal(0));
        accountDetail.setInmoney(exchange);
        accountDetail.setBalance(new BigDecimal(form.getTransferMoney()));
        accountDetail.setProofDate(endtime);
        accountDetail.setOfAccount(form.getOutaccount());
        accountDetail.setDeleted(AppConf.OFF);
        accountDetail.setCreatetime(timestamp);
        accountDetail.setTransactionDate(new Date());
        accountDetail.setOfCompany(form.getOfCompany());

        transactionDetailMapper.insert(detail);
        accountDetailService.save(accountDetail);

        inaccount.setTid(detail.getTid());
        inaccountService.save(inaccount);

        detail.setIid(inaccount.getIid());
        detail.setAccountDetailId(accountDetail.getAid());
        transactionDetailMapper.updateByPrimaryKeySelective(detail);
    }

    @Override
    public Account findByAname(String accountName) {
        return accountMapper.findByAname(accountName);
    }
}
